先講結論:taiwan-real-estate 抓的是內政部實價登錄的季度批次。2026-09-25 實測:下一季(115S3)的網址回 HTTP 200,但內容是 441 bytes 的 HTML「系統訊息」頁——不是 zip;當季(115S2)才是真的 14,705,972 bytes、236 個 CSV。地雷圖鑑又添一一條:狀態碼 200 不代表你拿到了你要的東西,副檔名要驗內容。
季代碼是民國年 + S + 季(115S2 = 2026 第 2 季)。批次檔隨申報進度開放,太早去抓下一季,伺服器不會 404,而是回一個 200 的錯誤說明頁。程式如果不檢查就把 441 bytes 存成 .zip,解壓縮才爆炸——运气好;更慘的是 downstream 直接吃到 HTML 還繼續解析。SKILL 的規矩:先驗證檔案真的是 zip(前兩個位元組 PK),當季抓不到就往前推一季。
解開之後還有三關。第一,UTF-8 BOM,要用 utf-8-sig 讀,不然第一個欄名會帶隱形字元。第二,雙標頭:第 1 列中文欄名、第 2 列英文欄名,資料從第 3 列開始——而那個英文列是逐字機翻的藝術品,「土地位置建物門牌」變成 land sector position building sector house number plate,看過一次就忘不了。第三,交易年月日是民國格式:1150601 = 2026-06-01。順帶,門牌欄位全形數字滿滿(南京東路三段89巷20號),Day 11 的教訓繼續適用。
台北市買賣檔(a_lvr_land_a.csv)5,607 筆資料列。2026-09-25 實測分佈:
| 項目 | 實測值 |
|---|---|
| 台北市買賣資料列 | 5,607(中山區 825、大安區 671、北投區 514) |
| 中山區房地交易 | 754 筆,單價中位數 277,884 元/㎡ |
| 換算坪價(×3.30579) | 約 91.9 萬元/坪 |
| 中山區車位交易 | 372 筆(文件範例那筆南京東路 370 萬車位還在) |
| 預售屋/租賃(台北市) | 955 筆/5,744 筆 |
還有一個誠實的細節:這是「2026 第 2 季」檔,但 5,607 筆裡交易年月日落在民國 115 年的只有 3,963 筆,尾巴一路拖到民國 102 年——實價登錄是申報制,遲申報的舊交易會混在當季檔案裡。所以回報必附兩句話:資料季度是哪季、申報落差大約一兩個月。
import csv
with open('/tmp/lvr/a_lvr_land_a.csv', encoding='utf-8-sig') as f:
rows = [r for r in csv.reader(f)][1:] # 去掉英文標頭列
# 中山區房地交易,依單價排序
deals = [r for r in rows if r[0] == '中山區' and '房地' in r[1]]
for r in deals[:5]:
print(r[7], r[2][:20], '總價', r[21], '單價/㎡', r[22])
資料源:內政部不動產交易實價查詢服務網 plvr.land.moi.gov.tw,DownloadSeason?season=115S2&type=zip&fileName=lvr_landcsv.zip,免 key、免登入。
第 18 天。政府資料給你的永遠是「檔案」,不是「答案」——這次的檔案誠實地告訴你:下一季還沒生,這一季裡面還混著五年前的遲到申報。